#include <string.h> 
#include <stdio.h> 

#include <avr/io.h>
#include <avr/interrupt.h>

#include <compat/deprecated.h> 

#include "BuffFifo.h"
#include "rtc.h"
#include "mail.h"

//time trig = 1ms
#define TIME_INTERVAL_100MS 50
#define TIME_INTERVAL_500MS 250

#define TIME_RTC_INTERVAL TIME_INTERVAL_500MS
#define TIME_TRC_1S 2//1
#define TIME_TRC_3S 6//3
#define TIME_TRC_30S 60//30
#define TIME_TRC_50S 100//50
#define TIME_TRC_MINUTE 120//60
#define TIME_TRC_20MIN TIME_TRC_MINUTE * 20

#define TIME_TRC_TASK_500MS 	1
#define TIME_TRC_TASK_1S 	2
#define TIME_TRC_TASK_50S 	100

unsigned int time_rtc; 
unsigned int time_rtc_task;

#define TIME_TRC_UPDATE_30S 30
static volatile unsigned int time_rtc_time_update = TIME_TRC_UPDATE_30S;

#define RTC_MANAGE_BUFF 8
BUFF_DECL_FIFO(RTCManageMsgBuf,RTC_MANAGE_BUFF);

#define RTC_SERIAL_BUFF 36
BUFF_DECL_FIFO(RTCSerialMsgBuf,RTC_SERIAL_BUFF);



#define TIME_INTERVAL_INIT 1

//#define TICKRATE 50	// time 20 ms
//#define TCNT2_INIT (0xFF-((F_CPU/1024)/TICKRATE))

#define TCNT2_INIT 0

void SendTimeUpdate(void);

// RTC variables
static volatile struct
{
	unsigned int mili_sec;
	unsigned char second;
	unsigned char minute;
	unsigned char hour;
}
sys_rtc_time;


ISR(TIMER2_OVF_vect)
{
	TCNT2 = TCNT2_INIT;
	
	//sys_rtc_time.second += 20; //20 milisec over flow
	sys_rtc_time.mili_sec += 1000; //100 milisec over flow
	
	if(sys_rtc_time.mili_sec >= 1000)
	{
		sys_rtc_time.mili_sec = 0;
		sys_rtc_time.second++;
		if(sys_rtc_time.second >= 60)
		{					
			sys_rtc_time.second -= 60;
			sys_rtc_time.minute++;
			if(sys_rtc_time.minute >= 60)
			{
				sys_rtc_time.minute = 0;
				sys_rtc_time.hour++;
				if(sys_rtc_time.hour >= 24)
				{
					sys_rtc_time.hour = 0;
				}		
			}
		}		
		
		if( time_rtc_time_update > 0)
		{
			time_rtc_time_update--;
		}
	}
}


void RTCManageMsgSend(char *ptr, unsigned char size)
{
	unsigned char i;
	
	for(i=0;i<size;i++)
	{
		if( BuffPutFifo(RTCManageMsgBuf,*ptr++) == FIFO_ERR)
		{
			break;
		}
	}
	SendMailFifo(MANAGE_DEV,0x01,size,(char *)RTCManageMsgBuf);
	
}

void RTCSerialMsgSend(char *ptr, unsigned char size)
{
	unsigned char i;
	
	for(i=0;i<size;i++)
	{
		if( BuffPutFifo(RTCSerialMsgBuf,*ptr++) == FIFO_ERR)
		{
			break;
		}
	}
	//SendMailFifo(SERIAL_DEV,0x01,size,(char *)RTCSerialMsgBuf);
	SendMailFifo(SERIAL_DEV,0x01,i,(char *)RTCSerialMsgBuf);
	
}


							
void InitRTC( void )
{	
	// //128 (From prescaler)
	sbi(TCCR2, CS20); cbi(TCCR2, CS21); sbi(TCCR2, CS22);
	
	//1024 (From prescaler)
	//sbi(TCCR2, CS20); sbi(TCCR2, CS21); sbi(TCCR2, CS22);

	//(No prescaling
	//sbi(TCCR2, CS20); cbi(TCCR2, CS21); cbi(TCCR2, CS22);
	
	//Timer register
	TCNT2 = TCNT2_INIT;
	
	//Output Compare register
	OCR2  = 0;
	
	//Asynchronous Status set to enable
	sbi(ASSR, AS2); //
	
	//Timer/Counter Interrupt Mask
	cbi(TIMSK, OCIE2); //Compare Match Interrupt Disable
	sbi(TIMSK, TOIE2); //Overflow Interrupt Enable
				
	time_rtc = TIME_RTC_INTERVAL;
	time_rtc_task = TIME_TRC_TASK_500MS;
	time_rtc_time_update = TIME_TRC_UPDATE_30S;
	
	BUFF_INIT_FIFO(RTCManageMsgBuf);
	BUFF_INIT_FIFO(RTCSerialMsgBuf);
}



void TimeRTC( void )
{
	if(time_rtc > 0)
	{
		time_rtc--;
		if(time_rtc==0)
		{		
			if(time_rtc_task>0)
			{
				time_rtc_task--;
			}
			time_rtc = TIME_RTC_INTERVAL;
		}
	}
}


void RTCMail(unsigned char act, unsigned char size, char * pbuf)
{
	if(act==0x01)
	{
		if(size == 2)
		{
			sys_rtc_time.hour = *(pbuf+0);
			sys_rtc_time.minute = *(pbuf+1);			
			sys_rtc_time.mili_sec = 0;
			sys_rtc_time.second = 0;			
			time_rtc_time_update = TIME_TRC_UPDATE_30S;
		}
	}
	else if(act==0x02)
	{
		SendTimeUpdate();
	}

}

void SendTimeUpdate(void)
{
	unsigned char rtc_time[2]; 
	
	rtc_time[0] = sys_rtc_time.hour;
	rtc_time[1] = sys_rtc_time.minute;
	
	RTCManageMsgSend((char *)&rtc_time,sizeof(rtc_time));
	
}

void RTCTask( void )
{
	if(time_rtc_task==0)
	{
	
		time_rtc_task = TIME_TRC_TASK_1S;		
	}
	
	if(time_rtc_time_update==0)
	{
		time_rtc_time_update = TIME_TRC_UPDATE_30S;		
		SendTimeUpdate();
	}
	
	
}
